Newer
Older
taehui / taehui-fe / src / app / [language] / forum / components / TextView.tsx
@Taehui Taehui on 17 Mar 2 KB 2024-03-17 오후 2:12
import scss from "@/app/[language]/forum/components/TextView.module.scss";
import useGetHit from "@/app/[language]/forum/query/useGetHit";
import AvatarTitle from "@/components/AvatarTitle";
import { getHitTexts, tag } from "@/utilities/Utility";
import { sanitize } from "dompurify";
import { useTranslations } from "next-intl";
import { useEffect, useMemo, useState } from "react";
import { Badge, Col, Row } from "reactstrap";
import { getDatetime } from "taehui-ts/date";

const TextView = ({
  forumTitle,
  title,
  text,
  avatarID,
  avatarName,
  date,
  hitCount,
}: {
  forumTitle: string;
  title: string;
  text: string;
  avatarID: string;
  avatarName: string;
  date?: string;
  hitCount?: number;
}) => {
  const hitTexts = useMemo(() => getHitTexts(text), [text]);
  const [textHTMLContents, setTextHTMLContents] = useState("");

  const t = useTranslations();

  const { data: hit, isFetched: isHitLoaded } = useGetHit(hitTexts);

  useEffect(() => {
    setTextHTMLContents(
      sanitize(tag(t, text, {}, scss.essay), {
        ADD_ATTR: ["target"],
      }),
    );
  }, [t, text]);

  useEffect(() => {
    if (isHitLoaded) {
      setTextHTMLContents(
        sanitize(
          tag(
            t,
            text,
            Object.fromEntries(hitTexts.map((hitText, i) => [hitText, hit[i]])),
            scss.essay,
          ),
          {
            ADD_ATTR: ["target"],
          },
        ),
      );
    }
  }, [hit, hitTexts, isHitLoaded, t, text]);

  return (
    <>
      <Row className="g-0">
        <Col className="m-1">
          <Badge>{forumTitle}</Badge>
        </Col>
      </Row>
      <Row className="g-0">
        <AvatarTitle avatarID={avatarID} avatarName={avatarName}>
          <span>{title}</span>
        </AvatarTitle>
        <Col className="m-1" xs="auto">
          {typeof hitCount === "number" && (
            <>
              <span>{getDatetime(date)}</span>
              <br />
              <span>{t("hitCount", { hitCount })}</span>
            </>
          )}
        </Col>
      </Row>
      <Row className="g-0">
        <Col className="m-1">
          <span
            className="ln"
            dangerouslySetInnerHTML={{
              __html: textHTMLContents,
            }}
          />
        </Col>
      </Row>
    </>
  );
};

export default TextView;